home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
iconv8_s.arc
/
ICONT.ARC
/
TSYM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-28
|
14KB
|
546 lines
/*
* tsym.c -- functions for symbol table management.
*/
#include "..\h\config.h"
#include "general.h"
#include "tproto.h"
#include "globals.h"
#include "trans.h"
#include "token.h"
#include "tsym.h"
#ifndef VarTran
#include "lfile.h"
#endif /* VarTran */
/*
* Prototypes.
*/
hidden struct tgentry *alcglob
Params((struct tgentry *blink, char *name,int flag,int nargs));
hidden struct tientry *alcid Params((char *nam,int len));
hidden struct tcentry *alclit
Params((struct tcentry *blink, char *name, int len,int flag));
hidden struct tlentry *alcloc
Params((struct tlentry *blink, char *name,int flag));
hidden struct tcentry *clookup Params((char *id,int flag));
hidden struct tgentry *glookup Params((char *id));
hidden struct tlentry *llookup Params((char *id));
hidden novalue putglob
Params((char *id,int id_type, int n_args));
hidden int streq Params((int len,char *s1,char *s2));
#ifdef DeBugTrans
novalue cdump Params((noargs));
novalue gdump Params((noargs));
novalue ldump Params((noargs));
#endif /* DeBugTrans */
/*
* putid - install the identifier named by the string starting at strf
* and extending for len bytes. The installation entails making an
* entry in the identifier hash table and then making an identifier
* table entry for it with alcid. A side effect of installation
* is the incrementing of strf by the length of the string, thus
* "saving" it.
*
* Nothing is changed if the identifier has already been installed.
*/
char *putid(len)
int len;
{
register int hash;
register char *s;
register struct tientry *ip;
int l;
/*
* Compute hash value by adding bytes and masking result with imask.
* (Recall that imask is ihsize-1.)
*/
s = strf;
hash = 0;
l = len;
while (l--)
hash += *s++ & 0377;
s = strf;
l = len;
hash &= imask;
/*
* If the identifier hasn't been installed, install it.
*/
if ((ip = ihash[hash]) != NULL) { /* collision */
for (;;) { /* work down i_blink chain until id is found or the
end of the chain is reached */
if (l == ip->i_length && streq(l, s, ip->i_name))
return (ip->i_name); /* id is already installed */
if (ip->i_blink == NULL) { /* end of chain */
ip->i_blink = alcid(s,l);
strf += l;
return s;
}
ip = ip->i_blink;
}
}
/*
* Hashed to an empty slot.
*/
ihash[hash] = alcid(s,l);
strf += l;
return s;
}
/*
* streq - compare s1 with s2 for len bytes, and return 1 for equal,
* 0 for not equal.
*/
static int streq(len, s1, s2)
register int len;
register char *s1, *s2;
{
while (len--)
if (*s1++ != *s2++)
return 0;
return 1;
}
/*
* alcid - get the next free identifier table entry, and fill it in with
* the specified values.
*/
static struct tientry *alcid(nam, len)
char *nam;
int len;
{
register struct tientry *ip;
if (ifree >= &itable[isize])
tsyserr("out of identifier table space");
ip = ifree++;
ip->i_blink = NULL;
ip->i_name = nam;
ip->i_length = len;
return ip;
}
#ifndef VarTran
/*
* loc_init - clear the local symbol table.
*/
novalue loc_init()
{
register struct tlentry **lp;
register struct tcentry **cp;
static int maxlfree = 0;
static int maxcfree = 0;
/* clear local table */
maxlfree = (maxlfree > lfree-ltable) ? maxlfree : lfree-ltable;
for (lp = lhash; lp < &lhash[lhsize]; lp++)
*lp = NULL;
lfree = ltable;
/* clear constant table */
maxcfree = (maxcfree > ctfree-ctable) ? maxcfree : ctfree-ctable;
for (cp = chash; cp < &chash[chsize]; cp++)
*cp = NULL;
ctfree = ctable;
}
/*
* install - put an identifier into the global or local symbol table.
* The basic idea here is to look in the right table and install
* the identifier if it isn't already there. Some semantic checks
* are performed.
*/
novalue install(name, flag, argcnt)
char *name;
int flag, argcnt;
{
union {
struct tgentry *gp;
struct tlentry *lp;
} p;
switch (flag) {
case F_Global: /* a variable in a global declaration */
if ((p.gp = glookup(name)) == NULL)
putglob(name, flag, argcnt);
else
p.gp->g_flag |= flag;
break;
case F_Proc|F_Global: /* procedure declaration */
case F_Record|F_Global: /* record declaration */
case F_Builtin|F_Global: /* external declaration */
if ((p.gp = glookup(name)) == NULL)
putglob(name, flag, argcnt);
else if ((p.gp->g_flag & (~F_Global)) == 0) { /* superfluous global
declaration for
record or proc */
p.gp->g_flag |= flag;
p.gp->g_nargs = argcnt;
}
else /* the user can't make up his mind */
tfatal("inconsistent redeclaration", name);
break;
case F_Static: /* static declaration */
case F_Dynamic: /* local declaration (possibly implicit?) */
case F_Argument: /* formal parameter */
if ((p.lp = llookup(name)) == NULL)
putloc(name,flag);
else if (p.lp->l_flag == flag) /* previously declared as same type */
tfatal("redeclared identifier", name);
else /* previously declared as different type */
tfatal("inconsistent redeclaration", name);
break;
default:
tsyserr("install: unrecognized symbol table flag.");
}
}
/*
* putloc - make a local symbol table entry and return the index
* of the entry in lhash. alcloc does the work if there is a collision.
*/
int putloc(id,id_type)
char *id;
int id_type;
{
register struct tlentry *ptr;
if ((ptr = llookup(id)) == NULL) { /* add to head of hash chain */
ptr = lhash[lhasher(id)];
lhash[lhasher(id)] = alcloc(ptr, id, id_type);
return (lhash[lhasher(id)] - ltable);
}
return (ptr - ltable);
}
/*
* putglob makes a global symbol table entry. alcglob does the work if there
* is a collision.
*/
static novalue putglob(id, id_type, n_args)
char *id;
int id_type, n_args;
{
register struct tgentry *ptr;
if ((ptr = glookup(id)) == NULL) { /* add to head of hash chain */
ptr = ghash[ghasher(id)];
ghash[ghasher(id)] = alcglob(ptr, id, id_type, n_args);
}
}
/*
* putlit makes a constant symbol table entry and returns the index
* of the entry in chash. alclit does the work if there is a collision.
*/
int putlit(id, idtype, len)
char *id;
int len, idtype;
{
register struct tcentry *ptr;
if ((ptr = clookup(id,idtype)) == NULL) { /* add to head of hash chain */
ptr = chash[chasher(id)];
chash[chasher(id)] = alclit(ptr, id, len, idtype);
return (chash[chasher(id)] - ctable);
}
return (ptr - ctable);
}
/*
* llookup looks up id in local symbol table and returns pointer to
* to it if found or NULL if not present.
*/
static struct tlentry *llookup(id)
char *id;
{
register struct tlentry *ptr;
ptr = lhash[lhasher(id)];
while (ptr != NULL && ptr->l_name != id)
ptr = ptr->l_blink;
return ptr;
}
/*
* glookup looks up id in global symbol table and returns pointer to
* to it if found or NULL if not present.
*/
static struct tgentry *glookup(id)
char *id;
{
register struct tgentry *ptr;
ptr = ghash[ghasher(id)];
while (ptr != NULL && ptr->g_name != id) {
ptr = ptr->g_blink;
}
return ptr;
}
/*
* clookup looks up id in constant symbol table and returns pointer to
* to it if found or NULL if not present.
*/
static struct tcentry *clookup(id,flag)
char *id;
int flag;
{
register struct tcentry *ptr;
ptr = chash[chasher(id)];
while (ptr != NULL && (ptr->c_name != id ||